
int counter =0;

#include "ddl_config.h"

#define USE_XTAL 0      /*使用HSE*/
#define USE_PLL  1      /*使用PLL*/

#define USE_GPIO 1      /*测试GPIO的翻转速度*/

#if USE_GPIO
#include "hc32f460_gpio.h"
#endif

#if USE_XTAL
#include "hc32f460_clk.h"
void CLK_SetSysClkSource(en_clk_sys_source_t enTargetSysSrc);
int clk_init(){
    CLK_SetSysClkSource(ClkSysSrcXTAL);
}
#elif USE_PLL
#include "system_hc32f460.h"
#include "hc32f460_clk.h"
#include "hc32f460_sram.h"
#include "hc32f460_efm.h"
#include "hc32f460_pwc.h"
int clk_init(){
    stc_clk_sysclk_cfg_t    stcSysClkCfg;
    stc_clk_xtal_cfg_t      stcXtalCfg;
    stc_clk_mpll_cfg_t      stcMpllCfg;
    stc_sram_config_t       stcSramConfig;

    MEM_ZERO_STRUCT(stcSysClkCfg);
    MEM_ZERO_STRUCT(stcXtalCfg);
    MEM_ZERO_STRUCT(stcMpllCfg);
    MEM_ZERO_STRUCT(stcSramConfig);

    //设置总线时钟分频
    stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;
    stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;
    stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;
    stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;
    stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;
    stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;
    stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;
    (&stcSysClkCfg);

    //开启xtal
    stcXtalCfg.enMode = ClkXtalModeOsc;
    stcXtalCfg.enDrv = ClkXtalLowDrv;
    stcXtalCfg.enFastStartup = Enable;
    CLK_XtalConfig(&stcXtalCfg);
    CLK_XtalCmd(Enable);

    //配置sram的等待时钟
    stcSramConfig.u8SramIdx = Sram12Idx | Sram3Idx | SramHsIdx | SramRetIdx;
    stcSramConfig.enSramRC = SramCycle2;
    stcSramConfig.enSramWC = SramCycle2;
    SRAM_Init(&stcSramConfig);

    //重新设置等待时钟
    EFM_Unlock();
    EFM_SetLatency(EFM_LATENCY_4);
    EFM_Lock();

    //配置PLL
    //频率 XTAL / pllmDiv * plln / PllpDIv = 200
    stcMpllCfg.pllmDiv = 1ul;
    stcMpllCfg.PllpDiv = 2ul;
    stcMpllCfg.PllqDiv = 2ul;
    stcMpllCfg.PllrDiv = 2ul;

    int freq = 200000000;           //默认频率
    int mul = freq * stcMpllCfg.PllpDiv / stcMpllCfg.pllmDiv /XTAL_VALUE;

    stcMpllCfg.plln    = mul;
    CLK_SetPllSource(ClkPllSrcXTAL);
    CLK_MpllConfig(&stcMpllCfg);

    /* Enable MPLL. */
    CLK_MpllCmd(Enable);

    while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
    {
        ;
    }
    PWC_HS2HP();

    CLK_SetSysClkSource(CLKSysSrcMPLL);
}
#endif

#if USE_GPIO
__attribute__((optimize("O3")))
__attribute__((section(".data")))
void test_gpio(){
    stc_port_init_t init;
    memset(&init,0,sizeof(init));
    init.enPinMode = Pin_Mode_Out;
    PORT_Init(PortA,Pin00,&init);
    int x = 0;
    register uint32_t PA_SR_CR = (0x40053800 + 0x10*0 + 0x8);
    register uint32_t PA_CR = (0x40053800 + 0x10*0 + 0xa);
    while(1){
        #if 0
        if(x&1){
            PORT_SetBits(PortA,Pin00);
        }
        else{
            PORT_ResetBits(PortA,Pin00);
        }
        #elif 0
        // POSR,PORR, 置位与清位
        // 200MHz,翻转速度为5MHz
        *(volatile uint32_t*)PA_SR_CR = (1<<0) << ((x&1)*16);
        #else
        //低电平或者高电平状态持续时间大概是10ns. 主频为12*33/2,198MHz
        //也就是说.写GPIO时需要2个cycle (5ns*2)
        //翻转约为速度为50MHz. 如果加上程序跳转.则少很多
        //注:以上是*(volatile uint32_t*)(PA_SR_CR+0), 32位写时,是50MHz
        //但16位写是单周期,可以实现接近100MHz
        //所以如果是1cycle访问,需要16位读写.

        /*
            (包括指令周期)
                    |cpu cycle  |GPIO freq  |
        16bit write |1cycle     |~100MHz    |
        32bit write |2cycle     |~50MHz     |

        */
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        *(volatile uint16_t*)(PA_SR_CR+0) = 1;
        *(volatile uint16_t*)(PA_CR) = 1;
        #endif
        x++;
    }
}
#else
void test_gpio(){}
#endif

int main(int argc,char**argv){
    /*
        注:默认时钟是使用HSE:晶振.可以查看SystemCoreClock变量知道
        可能未开启时钟
    */
   #if USE_XTAL||USE_PLL
   clk_init();
   #endif

   test_gpio();

    while(1){
        counter++;
    }
    return 0;
}
